/*
 * Copyright (C) 2008 Peter Kling
 * 
 * This file is part of 'A Kind of Billiard', a graphical billiard simulation.
 * 
 * 'A Kind of Billiard' is free software: you can redistribute it and/or modify it under the terms of the GNU General
 * Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
 * later version.
 * 
 * 'A Kind of Billiard' is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with 'A Kind of Billiard'. If not, see
 * <http://www.gnu.org/licenses/>.
 */

package de.akob.modeling;

import java.util.ArrayList;
import java.util.HashMap;

/**
 * Data structure that manages a collection of edges. It provides easy access to edges if one knows the vertices that
 * form the edge.
 * 
 * TODO: if two unequal objects happen to have the same hash code, this can cause problems in the <code>add</code> and
 * <code>get</code> methods.
 */
public class EdgeDB {
	private ArrayList<Edge>                        edges  = new ArrayList<Edge>();
	private HashMap<Vertex, HashMap<Vertex, Edge>> edgeDB = new HashMap<Vertex, HashMap<Vertex, Edge>>();
	
	/**
	 * If the database does not already contain an edge connecting the given vertices, such an edge will be added to the
	 * database. Otherwise, nothing happens.
	 * 
	 * @param a first vertex
	 * @param b second vertex
	 * @return whether the database was actually modified
	 */
	public boolean add(Vertex a, Vertex b) {
		if (a.hashCode() < b.hashCode())
			return add(b, a);
		if (a.hashCode() == b.hashCode() && a != b) {
			System.err.println("Warning: can not distinguish given (unequal) vertices");
			System.err.println("         --> this can cause unexpected behaviour (consider this a bug)");
		}
		
		if (getEdge(a, b) != null)
			return false;
		Edge e = new Edge(a, b);
		edges.add(e);
		HashMap<Vertex, Edge> aMap = edgeDB.get(a);
		if (aMap == null) {
			aMap = new HashMap<Vertex, Edge>();
			edgeDB.put(a, aMap);
		}
		aMap.put(b, e);
		return true;
	}
	
	/**
	 * Returns the edge connecting the given vertices. Note that edges are undirected. Thus, the order of the given
	 * vertices does not matter.
	 * 
	 * @param a first vertex
	 * @param b second vertex
	 * @return the edge connecting the vertices, or <code>null</code> if no such edge exists.
	 */
	public Edge getEdge(Vertex a, Vertex b) {
		if (a.hashCode() < b.hashCode())
			return getEdge(b, a);
		if (a.hashCode() == b.hashCode() && !a.equals(b)) {
			System.err.println("Warning: can not distinguish given (unequal) vertices");
			System.err.println("         --> this can cause unexpected behaviour (consider this a bug)");
		}
		
		HashMap<Vertex, Edge> aMap = edgeDB.get(a);
		if (aMap == null)
			return null;
		else
			return aMap.get(b);
	}
	
	/**
	 * Returns an array list containing all edges.
	 * 
	 * @return array list containing all edges
	 */
	public ArrayList<Edge> getEdges() {
		return edges;
	}
}
